package com.fuhao.service;

import java.util.concurrent.CountDownLatch;

import org.I0Itec.zkclient.IZkDataListener;

/**
 * zk分布式锁具体实现
 * @author zhang
 *
 */
public class ZookeeperDistrbuteLock extends ZookeeperAbstractLock{
	
	/**
	 * 判断是否获取zk连接
	 * true：获取到锁
	 * false：获取锁失败，进入等待状态
	 */
	@Override
	boolean tryLock() {
		try {
			//当没有连接去创建临时节点，会抛出异常
			zkClient.createEphemeral(PATH);
			return true;
		} catch (Exception e) {
			return false;
		}
	}

	/**
	 * 获取锁失败，进入等待状态
	 */
	@Override
	void waitLock() {
		//当进入等待状态，开启监听
		//使用事件监听，当监听到节点不存在，即zk断开连接节点被删除，此时唤醒
		IZkDataListener listener = new IZkDataListener() {
			//当节点被删除时候，进入此方法
			public void handleDataChange(String dataPath, Object data) throws Exception {
				if(countDownLatch != null) {
					//信号量-1,变为0，此时唤醒，去获取锁
					countDownLatch.countDown();
				}
			}
			//当节点改变时候，进入此方法
			public void handleDataDeleted(String dataPath) throws Exception {
				// TODO Auto-generated method stub
				
			}
			
		};
		//对PATH进行监听
		zkClient.subscribeDataChanges(PATH, listener);
		
		//判断节点是否存在,存在，进入等待
		if(zkClient.exists(PATH)) {
			countDownLatch = new CountDownLatch(1);
			try {
				//等待，当信号为0时候
				countDownLatch.await();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		//当唤醒后，关闭监听
		zkClient.unsubscribeDataChanges(PATH, listener);
	}

}
